package com.enmonster.commons;

import com.enmonster.annotations.*;
import com.enmonster.parsing.GenericTokenParser;
import com.enmonster.resolve.original.ModelOriginal;
import com.enmonster.resolve.original.ResultOriginal;

import java.lang.reflect.*;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Author wuxi
 * @create 2019/4/9 下午6:49
 *
 * 注解解析类
 */
public class InterResolveCommon {

    /**
     * 正则表达式
     */
    public static Pattern CANONICAL_PATTERN = Pattern.compile("(?<=\\{)(.+?)(?=\\})");

    /**
     * 解析 WxSelect 获取sql
     * @param method
     * @return
     */
    public static void wxSelectResolve(Method method, ModelOriginal modelOriginal){
        WxSelect wxSelect = method.getAnnotation(WxSelect.class);
        String handler = wxSelect.value();
        String sql = getSql(handler);
        modelOriginal.setSql(sql);
        modelOriginal.setType(SQLCommon.SELECT);
        modelOriginal.setOriginalSql(handler);
    }

    /**
     * 解析 WxInsert 获取sql
     */
    public static void wxInsertResolve(Method method, ModelOriginal modelOriginal){
        WxInsert wxInsert = method.getAnnotation(WxInsert.class);
        String handler = wxInsert.value();
        String sql = getSql(handler);
        modelOriginal.setSql(sql);
        modelOriginal.setType(SQLCommon.INSERT);
        modelOriginal.setOriginalSql(handler);
    }

    /**
     * 使用占位符获取最终sql
     * @param handler
     * @return
     */
    public static String getSql( String handler){
        GenericTokenParser parser = new GenericTokenParser("#{", "}", null);
        return  parser.parse(handler);
    }



    /**
     * 解析 WxResults 注解
     * @param method
     * @return
     */
    public static void wxResultsResolve(Method method, ResultOriginal resultOriginal){
        WxResults wxResults = method.getAnnotation(WxResults.class);
        WxResult[] results = wxResults.value();
        ConcurrentHashMap<String,String> resultMap = new ConcurrentHashMap();
        for (WxResult result : results){
            resultMap.put(result.property(),result.column());
        }
        resultOriginal.setResultParamMap (resultMap);
    }

    /**
     * 解析 WxResult
     * @param method
     * @param resultOriginal
     */
    public static void wxResultResolve(Method method, ResultOriginal resultOriginal){
        WxResult result = method.getAnnotation(WxResult.class);
        ConcurrentHashMap<String,String> resultMap = new ConcurrentHashMap();
        resultMap.put(result.property(),result.column());
        resultOriginal.setResultParamMap (resultMap);
    }


    /**
     * wxparam注解
     */
    public static void wxParamResolve(Method method,ModelOriginal modelOriginal, Object[] args) throws Exception{
        Parameter[] parameters = method.getParameters();
        ConcurrentHashMap<String,Object> paramMap = new ConcurrentHashMap();
        for (int i=0;i<parameters.length;i++) {
            Parameter parameter = parameters[i];
            Class paramObject = parameter.getType();
            //基本类型判断
            Boolean paramIsModel = paramIsModel(paramObject);
            if(paramIsModel){
                WxParam wxParam = parameter.getAnnotation(WxParam.class);
                if(null != wxParam){
                    paramMap.put(wxParam.value(),args[i]);
                }
            }else{
                Field[] declaredFields = args[i].getClass().getDeclaredFields();
                for (Field field : declaredFields) {
                    String fieldName = field.getName();
                    // 设置允许私有访问
                    field.setAccessible(true);
                    Object fieldValue = field.get(args[i]);
                    if(fieldValue == null) {
                        continue;
                    }
                    paramMap.put(fieldName,fieldValue);
                }
            }
        }
        modelOriginal.setParamMap(paramMap);
        sortParam(modelOriginal);
    }


    /**
     * 参数排序
     */
    public static void sortParam(ModelOriginal modelOriginal){
        ConcurrentHashMap<String,Object> paramMap =  modelOriginal.getParamMap();
        String originalSql = modelOriginal.getOriginalSql();
        Matcher mat = CANONICAL_PATTERN.matcher(originalSql);
        List<Object> paramValues = new ArrayList<>();
        while(mat.find()){
            paramValues.add(paramMap.get(mat.group()));
        }
        modelOriginal.setParamxEcuteList(paramValues);
    }

    /**
     * 判断参数类型是不是引用类型
     * @return
     */
    public static Boolean paramIsModel(Class paramType){
        Boolean result = false;
        //随便加引用类型
        if(String.class.toString().equals(paramType.toString())){
            result = true;
        }else if(Integer.class.toString().equals(paramType.toString())){
            result = true;
        }
        return  result;
    };

}
